home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
CUGUK
/
COMMS
/
C101.ZIP
/
UUPC11XS.ZIP
/
MAIL
/
ALIAS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-22
|
16KB
|
415 lines
/*--------------------------------------------------------------------*/
/* alias.c */
/* */
/* Smart routing and alias routines for pcmail. */
/* */
/* Copyright (C) 1989 Andrew H. Derbyshire */
/* */
/* Additional code */
/* Copyright (c) Richard H. Lamb 1985, 1986, 1987 */
/* Changes Copyright (c) Stuart Lynne 1987 */
/* */
/* Updates: */
/* */
/* 02 Oct 89 Alter large strings/structures to use */
/* malloc()/free() ahd */
/* 08 Feb 90 Correct failure of ExtractAddress to return */
/* non-names ahd */
/* 18 Mar 90 Move checkname() and associated routines into */
/* hostable.c ahd */
/* 22 Apr 90 Modify user_at_node to correctly handle .UUCP */
/* alias on local host. ahd */
/*--------------------------------------------------------------------*/
/*
* $Id: ALIAS.C 1.2 1992/11/22 21:06:14 ahd Exp $
*
* $Log: ALIAS.C $
* Revision 1.2 1992/11/22 21:06:14 ahd
* Use strpool for memory allocation
*
*/
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#ifndef __TURBOC__
#include <search.h>
#endif
#include "lib.h"
#include "hostable.h"
#include "security.h"
#include "usertabl.h"
#include "hlib.h"
#include "alias.h"
#include "address.h"
static size_t AliasCount = 0;
static struct AliasTable *alias = NULL;
int nickcmp( const void *a, const void *b );
static size_t LoadAliases( void ) ;
currentfile();
/*--------------------------------------------------------------------*/
/* I n i t R o u t e r */
/* */
/* Verify, initialize the global routing data */
/*--------------------------------------------------------------------*/
boolean InitRouter()
{
boolean success = TRUE; /* Assume the input data is good */
struct HostTable *Hptr;
/*--------------------------------------------------------------------*/
/* Verify that the user gave us a good name server */
/*--------------------------------------------------------------------*/
Hptr = checkreal(E_mailserv);
if (Hptr == BADHOST)
{
printmsg(0,"mail server '%s' must be listed in SYSTEMS file",
E_mailserv);
success = FALSE;
}
else if (Hptr->hstatus == localhost) /* local system? */
{
printmsg(0,"'%s' is name of this host and cannot be mail server",
E_mailserv);
success = FALSE;
}
/*--------------------------------------------------------------------*/
/* Return to caller */
/*--------------------------------------------------------------------*/
return success;
} /* InitRouter */
/*--------------------------------------------------------------------*/
/* E x t r a c t N a m e */
/* */
/* Returns full name of user, and returns address if name */
/* is not available. */
/*--------------------------------------------------------------------*/
void ExtractName(char *result, char *column)
{
static int recursion = 0;
recursion++;
printmsg((recursion > 2) ? 1:8,
"ExtractName: Getting name from '%s'",column);
ExtractAddress(result, column, TRUE); /* Get the full name */
if (!strlen(result)) /* Did we get the name? */
{ /* No --> Get the e-mail address */
char addr[MAXADDR];
char path[MAXADDR];
char node[MAXADDR];
char *fullname;
ExtractAddress(addr,column, FALSE);
user_at_node(addr,path,node,result);
/* Reduce address to basics */
fullname = AliasByAddr(node,result);
if (fullname == NULL)
{
strcat(result,"@");
strcat(result,node);
}
else
strcpy(result,fullname);
}
printmsg((recursion > 2) ? 1: 8,"ExtractName: name is '%s'",result);
recursion--;
return;
} /*ExtractName*/
/*--------------------------------------------------------------------*/
/* B u i l d A d d r e s s */
/* */
/* Builds a standard address format, with aliasing as */
/* required. */
/*--------------------------------------------------------------------*/
void BuildAddress(char *result, const char *input)
{
char addr[MAXADDR];
char name[MAXADDR];
char user[MAXADDR];
char path[MAXADDR];
char node[MAXADDR];
char *fulladdr;
/*--------------------------------------------------------------------*/
/* It must be a real address, possibly with a name attached; get */
/* the address portion, break the address into user and node, and */
/* then see if we know the person by address */
/*--------------------------------------------------------------------*/
ExtractAddress(addr,input,FALSE); /* Get user e-mail addr */
user_at_node(addr,path,node,user); /* Break address down */
fulladdr = AliasByAddr(node,user); /* Alias for the address? */
if (fulladdr != NULL) /* Yes --> Use it */
{
strcpy(result,fulladdr);
return;
} /* if */
/*--------------------------------------------------------------------*/
/* We don't know the address yet; get the name the user provided, */
/* and then normalize the address */
/*--------------------------------------------------------------------*/
ExtractAddress(name,input,TRUE); /* Also get their name */
if (strlen(name)) /* Did we find a name for user? */
{ /* Yes --> Return it */
char *s = strchr(node, '.');
if ((s == NULL) || equalni( s, ".UUCP", 5))
/* Simple name or UUCP domain? */
{ /* Yes--> Use original address */
size_t pathlen = strlen(path);/* Save len of orig path */
if ((pathlen > strlen(addr)) &&
(!equal(node,path)) && /* Target not a known host? */
equaln(addr,path, strlen(path)) && /* & host starts */
(addr[pathlen] == '!')) /* ...the address? */
fulladdr = &addr[pathlen + 1]; /* Yes --> Drop it */
else
fulladdr = addr; /* No --> Use full address */
sprintf(result,"(%s) %s", name, addr);
} /* (strchr(node, '.') == NULL) */
else /* No --> Use RFC-822 format */
sprintf(result,"\"%s\" <%s@%s>", name, user, node);
} /* if strlen(name) */
else
strcpy(result,addr); /* No name, just use the original */
} /* BuildAddress */
/*--------------------------------------------------------------------*/
/* A l i a s B y N i c k */
/* */
/* Locate a mail address by search the alias table. Returns TRUE */
/* if alias found and has address, otherwise FALSE. */
/*--------------------------------------------------------------------*/
char *AliasByNick(const char *nick)
{
int upper;
int lower;
if (!AliasCount)
AliasCount = LoadAliases();
upper = AliasCount - 1;
lower = 0;
while (upper >= lower)
{
int midpoint;
int hit;
midpoint = ( upper + lower ) / 2;
hit = stricmp(nick,alias[midpoint].anick);
if (!hit)
return alias[midpoint].afull;
if ( hit > 0 )
lower = midpoint + 1;
else
upper = midpoint - 1;
}
return NULL;
}
/*--------------------------------------------------------------------*/
/* A l i a s B y A d d r */
/* */
/* Locate a mail address by search the alias table. Returns TRUE */
/* if alias found and has address, otherwise FALSE */
/*--------------------------------------------------------------------*/
char *AliasByAddr(const char *node, const char *user)
{
size_t current = 0;
if (!AliasCount)
AliasCount = LoadAliases();
while (current < AliasCount)
{
int hit;
hit = stricmp(node,alias[current].anode);
if (!hit)
{
hit = stricmp(user,alias[current].auser);
if (!hit)
return alias[current].afull;
}
current++;
}
return NULL;
}
/*--------------------------------------------------------------------*/
/* L o a d A l i a s e s */
/* */
/* Initializes the address alias table; returns number of aliases */
/* loaded */
/*--------------------------------------------------------------------*/
size_t LoadAliases(void)
{
FILE *ff;
char buf[BUFSIZ];
char *token;
size_t elements = 0;
size_t max_elements = UserElements + 20;
size_t subscript;
struct AliasTable *hit; /* temporary pointer for searching */
struct AliasTable target;
checkuser( E_mailbox ); /* Force the table to be loaded */
alias = calloc(max_elements, sizeof(*alias));
checkref(alias);
/*--------------------------------------------------------------------*/
/* Actually load the alias table */
/*--------------------------------------------------------------------*/
if (E_aliases != NULL ) /* Did the user specify aliases file? */
{
ff = FOPEN(E_aliases, "r", TEXT);
if (ff == NULL)
{
printerr(E_aliases);
return elements;
} /* if */
while (! feof(ff))
{
if (fgets(buf,BUFSIZ,ff) == NULL) /* Try to read a line */
break; /* Exit if end of file */
token = strtok(buf," \t\n");
if (token == NULL) /* Any data? */
continue; /* No --> read another line */
if (token[0] == '#')
continue; /* Line is a comment; loop again */
/* Add the alias to the table. Note that we must add the nick */
/* to the table ourselves (rather than use lsearch) because */
/* we must make a copy of the string; the *token we use for */
/* the search is in the middle of our I/O buffer! */
/*
/* I was burned, _you_ have been warned. */
target.anick = token;
hit = (void *) lfind(&target, alias, &elements , sizeof(alias[0]),
nickcmp);
if (hit == NULL)
{
char node[MAXADDR];
char user[MAXADDR];
char path[MAXADDR];
char addr[MAXADDR];
char *eos;
if (elements == max_elements)
{
max_elements = max_elements * 2;
alias = realloc(alias, max_elements * sizeof(*alias));
checkref(alias);
}
alias[elements].anick = newstr(token);
token = strtok(NULL,""); /* Get rest of string */
while ( strlen(token) && isspace(*token))
token++;
eos = token + strlen(token) - 1;
while ( strlen(token) && isspace(*eos))
{
*eos = '\0';
eos--;
}
alias[elements].afull = newstr(token);
ExtractAddress(addr,alias[elements].afull,FALSE);
user_at_node(addr,path,node,user);
alias[elements].anode = newstr(node);
alias[elements].auser = newstr(user);
elements += 1;
}
else
printmsg(0,"LoadAliases: Duplicate alias '%s' in table",token);
}
fclose(ff);
} /* if (E_aliases != NULL ) */
/*--------------------------------------------------------------------*/
/* Add the local users as final aliases in table */
/*--------------------------------------------------------------------*/
alias = realloc(alias, (elements + UserElements) * sizeof(*alias));
/* Resize table to final known size */
checkref(alias);
for ( subscript = 0; subscript < UserElements; subscript++, elements++)
{
alias[elements].anick = ""; /* No nickname, only good for addr */
if (bflag[F_BANG])
sprintf(buf, "(%s) %s!%s",
users[subscript].realname, E_fdomain,
users[subscript].uid);
else
sprintf(buf, "\"%s\" <%s@%s>", users[subscript].realname,
users[subscript].uid, E_fdomain );
alias[elements].afull = newstr(buf);
alias[elements].anode = E_nodename;
alias[elements].auser = users[subscript].uid;
} /* for */
/*--------------------------------------------------------------------*/
/* Now sort the table */
/*--------------------------------------------------------------------*/
qsort(alias, elements ,sizeof(alias[0]) , nickcmp);
return (elements) ;
} /*LoadAliases*/
/*--------------------------------------------------------------------*/
/* n i c k c m p */
/* */
/* Accepts indirect pointers to two strings and compares them using */
/* stricmp (case insensitive string compare) */
/*--------------------------------------------------------------------*/
int nickcmp( const void *a, const void *b )
{
return stricmp(((struct AliasTable *)a)->anick,
((struct AliasTable *)b)->anick);
} /*nickcmp*/